<template>
  <div class="login-app">
    <!-- 模糊背景图 -->
    <!-- <div class="filter"></div> -->
    <!-- 修改后的背景容器 -->
    <div
        class="background-container"
        :class="{ 'blur-active': isBlurActive }"
    >
      <div class="background-image"></div>
    </div>
    <div class="spoken">
      <span>新起点、新征程</span>
    </div>
    <!-- 登录进度模态框 -->
    <el-dialog
        title="登录中..."
        :visible.sync="loginModalVisible"
        width="30%"
        :close-on-click-modal="false"
        :show-close="false"
        :close-on-press-escape="false"
    >
      <div class="login-progress-container">
        <!-- 状态提示 -->
        <div class="status-messages">
          <div v-for="(step, index) in loginSteps" :key="index" class="status-item">
            <span>{{ step.text }}</span>
            <span class="status-icon">
	          <i v-if="step.status === 'success'" class="el-icon-success" style="color: #67C23A"></i>
	          <i v-else-if="step.status === 'error'" class="el-icon-error" style="color: #F56C6C"></i>
	          <i v-else class="el-icon-loading" style="color: #409EFF"></i>
	        </span>
          </div>
        </div>

        <!-- 进度条 -->
        <el-progress
            :percentage="loadingProgress"
            :stroke-width="12"
            style="margin-top: 20px;"
        ></el-progress>

        <!-- 步骤提示信息 -->
        <div class="step-messages" v-if="stepMessages.length > 0">
          <div v-for="(msg, index) in stepMessages" :key="index" class="step-message">
            <span class="time">[{{ msg.time }}]</span>
            <span>{{ msg.text }}</span>
          </div>
        </div>
      </div>
    </el-dialog>
    <!-- 登录表单 -->
    <div class="login-form">
      <div class="login-right">
        <div class="title" style="text-align: center;height: 40px;">
          <span style="color: #347ebc;font-size: 22px;font-weight: bold;">欢迎使用数字云诊所</span>
        </div>
        <div class="login-cont">
          <el-tabs v-model="activeName" @tab-click="handleClick">
            <el-tab-pane label="密码登录" name="first">
              <el-form :model="loginForm" ref="loginForm" :rules="rules">
                <el-form-item prop="userName">
                  <el-input
                      v-model="loginForm.userName"
                      autocomplete="off"
                      placeholder="请输入账号 / 用户名 / 员工编号 / 编号"
                      prefix-icon="el-icon-user-solid"
                      clearable
                  ></el-input>
                </el-form-item>
                <el-form-item prop="password">
                  <el-input
                      type="password"
                      v-model="loginForm.password"
                      autocomplete="off"
                      placeholder="请输入登录密码"
                      prefix-icon="el-icon-lock"
                      show-password
                      @keyup.enter.native="handleEnter"
                  ></el-input>
                </el-form-item>

                <div class="chose">
                  <el-checkbox-group v-model="checkList">
                    <el-checkbox v-model="checked">记住账户</el-checkbox>
                  </el-checkbox-group>
                </div>
                <el-form-item>
                  <el-button type="primary" @click="submitForm"><span style="font-size: 22px;">登  录</span></el-button>
                </el-form-item>
                <el-form-item>
                  <!-- <span class="forget" @click="gotoForgetPwd">忘记密码?</span> -->
                </el-form-item>
              </el-form>
            </el-tab-pane>
            <el-tab-pane label="手机短信登录" name="second" disabled>
              <el-form :model="loginForm" ref="loginForm" :rules="rules">
                <el-form-item prop="userName">
                  <el-input
                      v-model="loginForm.userName"
                      autocomplete="off"
                      placeholder="请输入手机号"
                      prefix-icon="el-icon-user-solid"
                      clearable
                  ></el-input>
                </el-form-item>
                <el-form-item prop="password">
                  <div class="left" style="display: flex;align-items: center;height: 40px;line-height: 40px;">
                    <el-input
                        style="flex: 4;"
                        type="password"
                        v-model="loginForm.password"
                        autocomplete="off"
                        placeholder="请输入验证码"
                        prefix-icon="el-icon-lock"
                        show-password
                    ></el-input>
                    <el-button type="primary" style="flex: 1;margin-top: 0px;margin-left: 8px;color:aliceblue"
                               @click="getYzm" :disabled="YzmDisabled">
                      <span v-if="YzmDisabled">{{ seconds + 's后重新发送' }}</span>
                      <span v-else>{{ YzmText }}</span>
                    </el-button>
                  </div>
                </el-form-item>
                <!-- 在登录表单的按钮上方添加进度条 -->
                <el-form-item>
                  <!-- 登录按钮 -->
                  <el-button
                      type="primary"
                      @click="submitForm"
                      :loading="loading"
                  >
                    <span style="font-size: 22px;">登 录</span>
                  </el-button>
                </el-form-item>
                <el-form-item>
                  <span class="forget" @click="centerDialogVisible = true">忘记密码?</span>
                </el-form-item>
              </el-form>
            </el-tab-pane>
          </el-tabs>
        </div>
      </div>
    </div>
    <!-- 添加注册 -->
    <el-dialog
        title="注册账号"
        :visible.sync="centerDialogVisible"
        width="50%"
        center
    >
      <div slot="header">
        <span>添加账号</span>
      </div>
      <!-- 内容 -->
      <div class="content">
        <el-form
            :model="addAccform"
            :rules="rules"
            ref="addAccform"
            label-width="100px"
        >
          <el-form-item label="用户名" prop="userName">
            <el-input
                v-model="addAccform.userName"
                autocomplete="off"
                clearable
                placeholder="请输入您的用户名"
            ></el-input>
          </el-form-item>
          <el-form-item label="密码" prop="password">
            <el-input
                type="password"
                v-model="addAccform.password"
                autocomplete="off"
                clearable
                show-password
                placeholder="请输入密码"
            ></el-input>
          </el-form-item>
          <el-form-item label="手机号" prop="phoneNumber">
            <el-input
                v-model="addAccform.phoneNumber"
                autocomplete="off"
                clearable
                placeholder="请输入手机号"
                @input="handleInput"
            ></el-input>
          </el-form-item>
          <el-form-item label="诊所名称" prop="clinicName">
            <el-input
                v-model="addAccform.clinicName"
                autocomplete="off"
                clearable
                placeholder="请输入诊所名称"
            ></el-input>
          </el-form-item>
          <!--              <el-form-item label="用户组" prop="userGroup">
                          <el-select
                            v-model="addAccform.userGroup"
                            placeholder="请选择"
                          >
                            <el-option value="普通管理员">普通管理员</el-option>
                            <el-option value="超级管理员">超级管理员</el-option>
                          </el-select>
                        </el-form-item> -->
          <el-form-item>
            <el-button type="primary" @click="resgiterform"
            >添加
            </el-button
            >
            <el-button @click="resetForm">重置</el-button>
            <el-button @click="centerDialogVisible = false"
            >取 消
            </el-button
            >
          </el-form-item>
        </el-form>
      </div>

    </el-dialog>
  </div>
</template>

<script>

// import { md5 } from 'js-md5'; // 引入
// import Base64 from 'js-base64';// 引入
import sha256 from 'js-sha256';
import {deleteUser, insertUser, login} from "@/api/user.js";
import {doccliniclist} from "@/api/cinic/cinic";
import watermark from "@/untils/watermark";
import dayjs from "dayjs";
import {addYbRquestData, getqdNo, toUploadLY} from "@/api/yb";
import {ybRequestTemplate} from "/src/untils/ybRequestTemplate.js"
import axios from "axios";

export default {
  components: {
    login,
    insertUser,
    deleteUser
  },

  data() {
    return {
      ip: process.env.VUE_APP_HOST,
      hostname: process.env.VUE_APP_NAME,
      machineId: process.env.VUE_APP_MACHINEID,
      isBlurActive: false, // 控制模糊效果的开关
      loadingProgress: 0, // 进度条百分比
      progressVisible: false, // 是否显示进度条
      progressInterval: null, // 进度条定时器
      informations: '',
      activeName: 'first',
      YzmText: '获取验证码',
      count: '', //倒计时
      timer: null, // 定时器
      seconds: 30, // 30秒 // 倒计时
      token: '', //token
      //表单数据
      addAccform: {
        userName: "",
        password: "",
        clinicName: "",
        phoneNumber: "",
        // userGroup:"",
      },
      checked: false,
      loading: false,
      YzmDisabled: false,// 是否正在倒计时
      centerDialogVisible: false,
      encodedText: '',
      decodedText: '',
      //判断登录时长
      timeOut: "",
      checkList: [],
      loginForm: {
        userName: "",
        password: "",
        docDeviceInfoVO: {
          browser: "",
          localIp: "",
          machineId: "",
          os: ""
        },
      },
      // 医保相关
      fwsId: '91510181725394828X_C',
      sqm: '4d5de31bc5ff4fdc862a57c63fd4fcef',
      lastSignDate: null, // 上次签到日期
      qdResult: null, // 医保签到响应结果
      qtResult: null, // 医保签退响应结果
      stepMessages: [], // 用于存储步骤提示信息
      lyToqdId: '', // 签到老游返回的id
      lyToqtId: '', // 签退老游返回的id
      signNo: '', // 从接口获取的签到流水号(编号)
      resData: {},
      //表单验证规则
      rules: {
        //账号
        account: [
          {required: true, message: "请输入用户名", trigger: "blur"},
          {min: 2, max: 8, message: "长度在2到8个字符", trigger: "blur"},
        ],
        //密码
        password: [
          {required: true, message: "请输入密码", trigger: "blur"},
          {min: 6, max: 12, message: "长度在6到12个字符", trigger: "blur"},
        ],
        // 手机号
        phoneNum: [
          {required: true, message: "请输入手机号", trigger: "blur"},
          {min: 11, max: 11, message: "手机号长度不正确！", trigger: "blur"},
        ],
        // 诊所名称
        zsName: [
          {required: true, message: "请输入诊所名", trigger: "blur"},
          {min: 2, max: 10, message: "长度在2到10个字符", trigger: "blur"},
        ],
      },
      // 新增的数据
      loginModalVisible: false,
      loginSteps: [
        {text: '账号密码验证', status: ''},
        {text: '验证最新版本', status: ''},
        {text: '医保签到', status: ''}
      ],
    };
  },

  created() {

  },
  mounted() {
    this.Time() //调用定时器
    // console.log('IP:', this.ip);
    // console.log('Hostname:', this.hostname);
    // console.log('Machine ID:', this.machineId);
    // 获取本机基本信息
    this.getSystemInfo();
    //this.handleYbSignIn();
    // 页面加载后触发模糊效果
    setTimeout(() => {
      this.isBlurActive = true
    }, 100)
    if (!window.crypto || !window.crypto.getRandomValues) {
      console.error('浏览器不支持Crypto API');
      this.$message.error('您的浏览器安全功能不完整，请升级浏览器');
    }
  },
  methods: {
    /* 获取本机基本信息 */
    getSystemInfo() {
      const systemInfo = {
        userAgent: navigator.userAgent, // 操作系统
        appName: navigator.appName, // 浏览器名称
        appVersion: navigator.appVersion, // 版本信息及浏览器运行的操作系统
        platform: navigator.platform, // 浏览器正在运行的操作系统平台
        language: navigator.language, // 浏览器语言
        screenWidth: screen.width, // 屏幕宽
        screenHeight: screen.height, // 屏幕高
        colorDepth: screen.colorDepth,// 屏幕颜色深度
        ip: this.ip, // 目前本机ip地址
        Hostname: this.hostname, // 本机用户组名
        MachineID: this.machineId,// 设备号
        informations: this.informations // 字段说明
      };

      this.systemInfo = systemInfo;
      localStorage.setItem("systemInfo", JSON.stringify(systemInfo));
    },
    // tabs
    handleClick(tab, event) {
      // console.log(tab, event);
    },
    Time() {
      setInterval(() => {
        this.seconds -= 1
        //刷新
        this.$router.go(0);
      }, 600000)
    },
    resgiter() {
      this.$refs.addAccform.style = "block";
    },
    //重置
    resetForm() {
      this.$refs.addAccform.resetFields();
    },
    //提交
    resgiterform() {
      //触发验证表单
      this.$refs.addAccform.validate(async (valid) => {
        if (valid) {
          //验证通过
          insertUser(this.addAccform).then(res => {
            // console.log(res);
            if (res.code === 200) {
              this.$message({
                message: res.message,
                type: "success",
              });
            } else {
              //验证失败
              // console.log("失败");
              this.$message.error(res.message);
            }
          })
        }
      });
    },
    //忘记密码？
    gotoForgetPwd() {
      this.$router.push('/forgetPassword');
    },
    // 回车键或按钮被点击
    handleEnter() {
      // 执行提交逻辑
      this.submitForm();
    },
    handleInput(value) {
      // 使用正则表达式来判断是否为数字，并对非数字进行处理
      const regex = /^[0-9]*$/;
      if (!regex.test(value)) {
        // 如果输入的不是数字，则将输入值设置为上一个有效的数字状态
        this.addAccform.phoneNum = value.substring(0, value.length - 1);
      }
    },
    //获取验证码
    getYzm() {
      if (this.YzmDisabled) {
        return; // 如果正在倒计时，则不执行获取验证码操作
      }
      // 开始倒计时
      this.YzmDisabled = true;
      this.$message({
        message: '验证码已发送！',
        type: 'success'
      });
      this.timer = setInterval(() => {
        if (this.seconds > 0) {
          this.seconds--;
        } else {
          // 倒计时结束，重置状态
          this.YzmDisabled = false;
          this.seconds = 30;
          clearInterval(this.timer); // 清除定时器
        }
      }, 1000);
    },

    // 登录
    async submitForm() {
      this.loginForm.docDeviceInfoVO.machineId = this.machineId;
      this.loginForm.docDeviceInfoVO.localIp = this.ip;
      this.loginForm.docDeviceInfoVO.browser = navigator.vendor;
      this.loginForm.docDeviceInfoVO.os = navigator.userAgent.slice(13, 13 + 27);

      // 触发验证表单
      this.$refs.loginForm.validate(async (valid) => {
        if (valid) {
          // 初始化状态
          this.loginModalVisible = true;
          this.loadingProgress = 0;
          this.loginSteps = this.loginSteps.map(step => ({...step, status: ''}));
          this.stepMessages = []; // 重置提示信息

          try {
            // 步骤1: 账号密码验证
            this.updateStepStatus(0, 'loading');
            this.addStepMessage('开始验证账号密码...');
            const loginRes = await login(this.loginForm);

            if (loginRes.code !== 200) {
              this.updateStepStatus(0, 'error');
              this.addStepMessage(`验证失败: ${loginRes.message || '未知错误'}`, {level: 'error'});
              this.$message.error(loginRes.message || '登录失败');
              this.loginModalVisible = false;
              return;
            }

            this.updateStepStatus(0, 'success');
            this.addStepMessage('账号密码验证成功');
            this.loadingProgress += 28;

            // 保存用户信息
            this.token = loginRes.data.token;
            localStorage.setItem('token', this.token);
            localStorage.setItem('userInfo', JSON.stringify(loginRes.data.user));
            localStorage.setItem('terminalId', JSON.stringify(loginRes.data.terminalId));
            localStorage.setItem('permissions', JSON.stringify(loginRes.data.permissions));

            // 步骤2: 验证最新版本
            this.updateStepStatus(1, 'loading');
            this.addStepMessage('正在验证系统版本...');
            const versionValid = await this.verifyYbUser(loginRes.data.user);

            if (!versionValid) {
              this.updateStepStatus(1, 'error');
              this.addStepMessage('版本验证失败', {level: 'error'});
              this.$message.error('版本验证失败');
              this.loginModalVisible = false;
              return;
            }

            this.updateStepStatus(1, 'success');
            this.addStepMessage('当前已是最新版本。');
            this.loadingProgress += 28;

            // 步骤3: 医保签到处理
            if (loginRes.data.user.isInsurance === '1') {
              this.updateStepStatus(2, 'loading');
              const today = dayjs().format('YYYY-MM-DD');
              const lastSignDate = localStorage.getItem('signedDates');

              // 检查是否当天已签到
              if (lastSignDate === today) {
                this.addStepMessage('今天医保已签到，正在登录中...', {
                  level: 'info',
                  duration: 2880 // 2.88秒
                });

                // 延迟2.88秒
                await new Promise(resolve => setTimeout(resolve, 2880));

                this.updateStepStatus(2, 'success');
                this.addStepMessage('登录中...');
                this.loadingProgress = 100;
              } else {
                // 检查是否需要先签退
                if (lastSignDate && lastSignDate !== today) {
                  this.addStepMessage(`检测到上次签到日期(${lastSignDate})与今天不同，正在执行签退...`);

                  // 执行签退
                  const signOutSuccess = await this.handleYbSignOut(loginRes.data.user);
                  if (!signOutSuccess) {
                    this.updateStepStatus(2, 'error');
                    this.addStepMessage('医保签退失败', {level: 'error'});
                    this.$message.error('医保签退失败');
                    return;
                  }

                  this.addStepMessage('医保签退成功，继续执行签到...');
                  // 清除历史签到记录
                  localStorage.removeItem('signedDates');
                  this.signNo = '';
                }

                // 执行签到
                this.addStepMessage('开始医保签到流程...');
                const signInSuccess = await this.handleYbSignIn(loginRes.data.user);
                if (signInSuccess) {
                  this.addStepMessage('医保签到成功');
                  this.updateStepStatus(2, 'success');
                } else {
                  this.updateStepStatus(2, 'error');
                  this.addStepMessage('医保签到失败', {level: 'error'});
                  this.$message.error('医保签到失败');
                }
              }
            } else {
              this.addStepMessage('当前用户无需医保签到');
              this.updateStepStatus(2, 'success');
            }

            this.loadingProgress = 100;

            // 登录成功处理
            await this.setUserWatermark(loginRes.data.user);
            this.$router.push({path: '/'});
            this.$message.success('登录成功');

          } catch (error) {
            console.error('登录过程中出错:', error);
            this.addStepMessage(`系统错误: ${error.message}`, {level: 'error'});
            this.$message.error('登录过程中出错');
          } finally {
            setTimeout(() => {
              this.loginModalVisible = false;
            }, 1500);
          }
        }
      });
    },

    // 通用保存医保响应方法
    // 保存医保响应方法（优化）
    async saveYbResponse(response, type) {
      try {
        // 根据类型设置infno
        const infno = type === 'signIn' ? '9001' : '9002';

        // 提取业务ID
        const id = type === 'signIn' ? this.lyToqdId : this.lyToqtId;

        if (!id) {
          this.addStepMessage('业务ID获取失败，无法保存记录', {level: 'warning'});
          return false;
        }

        const params = {
          data: JSON.stringify(response),
          id: id,
          infno: infno,
          type: type,
          timestamp: dayjs().format('YYYY-MM-DD HH:mm:ss')
        };

        const res = await toUploadLY(params);
        if (res.code === 200) {
          this.addStepMessage(`${type === 'signIn' ? '签到' : '签退'}记录已存档`);
          return true;
        }

        this.addStepMessage(`${type === 'signIn' ? '签到' : '签退'}记录保存失败: ${res.message}`, {level: 'warning'});
        return false;

      } catch (error) {
        console.error('保存医保响应失败:', error);
        this.addStepMessage(`保存记录失败: ${error.message}`, {level: 'error'});
        return false;
      }
    },

    // 重试机制
    async executeWithRetry(fn, maxRetries = 3) {
      let attempts = 0;
      while (attempts < maxRetries) {
        try {
          return await fn();
        } catch (error) {
          attempts++;
          this.addStepMessage(`操作失败，正在重试(${attempts}/${maxRetries})`, 'warning');
          await new Promise(resolve => setTimeout(resolve, 2000));
        }
      }
      throw new Error(`操作重试${maxRetries}次后失败`);
    },

    // 使用示例
    // this.executeWithRetry(() => this.handleYbSignOut(userData));

    // 新增方法：添加步骤提示信息
    addStepMessage(message, config = {}) {
      const msgObj = {
        text: typeof message === 'string' ? message : JSON.stringify(message),
        time: dayjs().format('HH:mm:ss'),
        level: config.level || 'info',
        persist: config.persist || false,
        duration: config.duration || 0,
        // 新增样式类名
        class: config.level === 'error' ? 'message-error' :
            (config.level === 'success' ? 'message-success' : 'message-info')
      };

      this.stepMessages.push(msgObj);

      // 自动隐藏非持久化消息
      if (msgObj.duration > 0 && !msgObj.persist) {
        setTimeout(() => {
          this.stepMessages = this.stepMessages.filter(m => m !== msgObj);
        }, msgObj.duration);
      }

      // 限制消息数量
      if (this.stepMessages.length > 10) {
        this.stepMessages.shift();
      }
    },

    // 更新步骤状态
    updateStepStatus(index, status) {
      this.$set(this.loginSteps, index, {
        ...this.loginSteps[index],
        status: status
      })
    },

    // 增加进度条进度
    increaseProgress() {
      this.loadingProgress += 10
      if (this.loadingProgress > 100) {
        this.loadingProgress = 100
      }
    },
    // 格式化进度条显示
    formatProgress(percentage) {
      return `${percentage}%`
    },

    // 验证最新版本
    async verifyYbUser(user) {
      try {
        // 1. 获取当前版本信息
        const currentVersion = process.env.VUE_APP_VERSION || '1.0.0';

        // 2. 模拟API响应 - 当前版本为最新版本
        const mockResponse = {
          code: 200,
          message: "success",
          data: {
            hasNewVersion: false,
            latestVersion: currentVersion, // 与当前版本相同
            forceUpdate: false,
            downloadUrl: "",
            releaseNotes: ""
          }
        };

        // 3. 模拟API调用延迟
        await new Promise(resolve => setTimeout(resolve, 2888));

        // 4. 处理版本检查结果
        if (mockResponse.code === 200) {
          const versionInfo = mockResponse.data;

          if (versionInfo.hasNewVersion) {
            // 有新版本可用 - 这里不会执行，因为hasNewVersion为false
            this.$message.warning(`发现新版本 ${versionInfo.latestVersion}，建议尽快更新`);

            if (versionInfo.forceUpdate) {
              // 强制更新 - 这里不会执行
              this.$confirm(`发现强制更新版本 ${versionInfo.latestVersion}，必须更新后才能继续使用`, '版本更新', {
                confirmButtonText: '立即更新',
                cancelButtonText: '退出',
                type: 'warning',
                showCancelButton: false,
                closeOnClickModal: false
              }).then(() => {
                window.location.href = versionInfo.downloadUrl;
              });
              return false;
            }
          } else {
            // 当前已是最新版本
            console.log('当前已是最新版本:', currentVersion);
          }

          // 版本检查通过
          return true;
        } else {
          // 版本检查失败，但允许继续登录
          console.error('版本检查失败:', mockResponse.message);
          return true;
        }
      } catch (error) {
        console.error('版本检查异常:', error);
        // 网络异常等情况，允许继续登录
        return true;
      }
    },

    // 医保签到相关
    // 在handleYbSignIn方法中，保存签到成功后返回的业务ID
    async handleYbSignIn(userData) {
      console.log('===== 开始执行医保签到流程 =====');
      try {
        const today = dayjs().format('YYYY-MM-DD');
        // 1. 构造医保请求
        const ybRequest = JSON.parse(JSON.stringify(ybRequestTemplate));
        this.machineId = this.machineId.slice(0, 20);
        ybRequest.body.infno = '9001';
        ybRequest.body.msgid = `${userData.clinicCode}${dayjs().format('YYYYMMDDHHmmss')}${this.getRandom4Digits()}`;
        ybRequest.body.mdtrtarea_admvs = userData.mdtrtareaAdmvs;
        ybRequest.body.recer_sys_code = '007';
        ybRequest.body.infver = 'V1.0';
        ybRequest.body.opter_type = '1';
        ybRequest.body.opter = userData.clinicCode;
        ybRequest.body.opter_name = userData.staffName;
        ybRequest.body.inf_time = dayjs().format('YYYY-MM-DD HH:mm:ss');
        ybRequest.body.fixmedins_code = userData.clinicCode;
        ybRequest.body.fixmedins_name = userData.clinicName;
        ybRequest.body.input.signIn = {
          opter_no: userData.staffId,
          mac: this.machineId,
          ip: this.ip
        }
        console.log('医保签到请求体:', JSON.stringify(ybRequest.body, null, 2));

        // 2. 先传给老游
        const newItem = {
          infno: 9001,
          mdtrtareaAdmvs: userData.mdtrtareaAdmvs,
          data: JSON.stringify(ybRequest.body),
          patientId: userData.staffId,
          patientName: userData.staffName
        }
        console.log('newItem内容:', JSON.stringify(newItem, null, 2));
        this.addStepMessage('正在准备医保签到数据...');
        const res = await addYbRquestData(newItem);

        if (res.code !== 200) {
          this.addStepMessage(`医保数据准备失败: ${res.message}`, {level: 'error'});
          return false;
        }

        this.addStepMessage('医保数据准备完成，开始调用接口...');
        this.lyToqdId = res.data.id;
        let responseData = res.data;

        // 3. 解析响应并设置请求头
        if (typeof responseData === 'string') {
          try {
            responseData = JSON.parse(responseData);
          } catch (parseError) {
            this.addStepMessage('解析医保响应数据失败', {level: 'error'});
            return false;
          }
        }

        ybRequest.headers.infosyscode = responseData.infosyscode;
        ybRequest.headers.hsf_signature = responseData.signature;
        ybRequest.headers.fixmedins_code = userData.clinicCode;
        ybRequest.headers.hsf_nonce = responseData.hsfNonce;
        ybRequest.headers.hsf_timestamp = responseData.hsfTimestamp;

        // 4. 调用医保接口
        const axiosConfig = {
          method: 'post',
          url: process.env.VUE_APP_BASE_YBHOST+`/eapdomain/callService`,
          baseURL: '',
          headers: ybRequest.headers,
          data: ybRequest.body,
        };

        const response = await axios(axiosConfig);
        this.qdResult = response;
        console.log('医保签到响应结果:', this.qdResult);
        this.addStepMessage('医保签到接口调用完成');

        // 5. 保存响应到老游
        const saveSuccess = await this.saveYbResponse(this.qdResult, 'signIn');
        if (!saveSuccess) {
          this.addStepMessage('医保签到记录保存失败', {level: 'warning'});
        }

        // 6. 处理结果
        if (this.qdResult.infcode === 0) {
          // 获取签到编号
          const signNoRes = await getqdNo();
          if (signNoRes.code === 200) {
            this.signNo = signNoRes.data.signNo;
            localStorage.setItem('signedDates', today);
            this.addStepMessage(`签到成功，业务ID: ${this.signNo}`);
            return true;
          } else {
            this.addStepMessage('获取签到流水号失败', {level: 'error'});
            return false;
          }
        } else {
          // 新增：检测特定错误信息
          const errorMsg = this.qdResult.err_msg || '未知错误';

          // 检查错误信息中是否包含特定关键词
          const keywords = ['已经', '签退', '明天', '签到'];
          const hasSpecialError = keywords.some(keyword => errorMsg.includes(keyword));

          if (this.qdResult.infcode === -1 && hasSpecialError) {
            // 特定错误处理
            this.updateStepStatus(2, 'warning');
            this.addStepMessage('经系统检测，医保功能暂不可用', {level: 'warning'});
            this.addStepMessage('正在登录中...');

            // 延迟1.8秒后继续登录
            await new Promise(resolve => setTimeout(resolve, 1800));

            // 标记为成功跳过签到
            this.updateStepStatus(2, 'success');
            return true;
          } else {
            // 其他错误处理
            this.updateStepStatus(2, 'error');
            this.addStepMessage(`医保签到失败: ${errorMsg}`, {level: 'error', duration: 4888});
            await new Promise(resolve => setTimeout(resolve, 2888));
            return false;
          }
        }

      } catch (error) {
        console.error('执行签到过程中出错:', error);
        this.addStepMessage(`医保签到异常: ${error.message}`, {level: 'error'});
        return false;
      } finally {
        console.log('===== 医保签到流程结束 =====');
      }
    },


    // 执行签到操作
    async executeSignIn(userData, today) {
      try {
        // 检查是否当天已签到
        const lastSignDate = localStorage.getItem('signedDates');
        if (lastSignDate === today) {
          return true; // 当天已签到，直接返回成功
        }
        const ybRequest = JSON.parse(JSON.stringify(ybRequestTemplate));
        this.machineId = this.machineId.slice(0, 20);
        ybRequest.body.infno = '9001';
        ybRequest.body.msgid = `${userData.clinicCode}${dayjs().format('YYYYMMDDHHmmss')}${this.getRandom4Digits()}`;
        ybRequest.body.mdtrtarea_admvs = userData.mdtrtareaAdmvs;
        ybRequest.body.recer_sys_code = '007';
        ybRequest.body.infver = 'V1.0';
        ybRequest.body.opter_type = '1';
        ybRequest.body.opter = userData.clinicCode;
        ybRequest.body.opter_name = userData.staffName;
        ybRequest.body.inf_time = dayjs().format('YYYY-MM-DD HH:mm:ss');
        ybRequest.body.fixmedins_code = userData.clinicCode;
        ybRequest.body.fixmedins_name = userData.clinicName;
        ybRequest.body.input.signIn = {
          opter_no: userData.staffId,
          mac: this.machineId,
          ip: this.ip
        }

        // 传给老游的数据 => 调用医保接口之前都需要先传给老游
        const newItem = {
          infno: 9001,
          mdtrtareaAdmvs: userData.mdtrtareaAdmvs,
          data: JSON.stringify(ybRequest.body),
          patientId: userData.staffId,
          patientName: userData.staffName
        }

        const res = await addYbRquestData(newItem);
        if (res.code === 200) {
          localStorage.setItem('signedDates', today);
          let responseData = res.data;
          this.lyToqdId = responseData.id
          console.log('签到9001老游返回的:', responseData);
          if (typeof responseData === 'string') {
            try {
              responseData = JSON.parse(responseData);
            } catch (parseError) {
              console.error('解析响应数据失败:', parseError);
              return false;
            }
          }

          ybRequest.headers.infosyscode = responseData.infosyscode;
          ybRequest.headers.hsf_signature = responseData.signature;
          ybRequest.headers.fixmedins_code = userData.clinicCode;
          ybRequest.headers.hsf_nonce = responseData.hsfNonce;
          ybRequest.headers.hsf_timestamp = responseData.hsfTimestamp;

          const axiosConfig = {
            method: 'post',
            url: process.env.VUE_APP_BASE_YBHOST+`/eapdomain/callService`,
            baseURL: '',
            headers: ybRequest.headers,
            data: ybRequest.body,
          };

          const response = await axios(axiosConfig);
          this.qdResult = response;
          console.log('签到响应：', this.qdResult);

          // 获取签到编号
          const signNoRes = await getqdNo();
          // console.log(signNoRes,'获取签到编号获取签到编号获取签到编号');
          if (signNoRes.code === 200) {
            this.signNo = signNoRes.data.signNo; // 存储从接口获取的signNo
            this.addStepMessage(`签到成功，业务ID: ${this.signNo}`);
          } else {
            throw new Error('获取签到流水号失败');
          }

          // 保存签到响应 to 老游
          await this.saveYbResponse(this.qdResult, 'signIn');

          if (this.qdResult.infcode === 0) {
            return true;
          } else {
            // 添加带延迟的错误提示
            this.addStepMessage(
                this.qdResult.err_msg + '医保服务暂时不可用',
                {
                  level: 'error',
                  duration: 4888
                }
            );
            // 延迟处理进度条
            await new Promise(resolve => setTimeout(resolve, 4888));
            this.loadingProgress = 100;
            return false;
          }

        }
        return false;
      } catch (error) {
        console.error('执行签到过程中出错:', error);
        return false;
      }
    },

    // 医保签退方法
    async handleYbSignOut(userData) {
      console.log('===== 开始执行医保签退流程 =====');
      console.log('步骤1: 获取签到编号');
      try {
        // 1. 获取签到编号
        console.log('调用getqdNo接口获取签到编号...');
        this.addStepMessage('正在获取签到流水号...');
        const signNoRes = await getqdNo();
        console.log('getqdNo接口返回:', signNoRes);

        if (signNoRes.code != 200) {
          console.error('获取签到编号失败:', signNoRes);
          this.addStepMessage('错误：获取签到流水号失败', {level: 'error'});
          return false;
        }

        // 2. 检查签到编号是否过期
        if (signNoRes.data.expire === true) {
          console.log('签到编号已过期，需要进行签退');
          this.addStepMessage('医保签到编码已过期，正在进行签退...', {level: 'warning'});

          // 使用获取到的过期signNo
          this.signNo = signNoRes.data.signNo;
          console.log('成功获取到过期的签到编号:', this.signNo);

          // 3. 构造医保签退请求
          console.log('步骤2: 构建医保签退请求');
          const ybRequest = JSON.parse(JSON.stringify(ybRequestTemplate));
          this.machineId = this.machineId.slice(0, 20);

          // 设置请求体参数
          this.machineId = this.machineId.slice(0, 20);
          ybRequest.body.infno = '9002';
          ybRequest.body.msgid = `${userData.clinicCode}${dayjs().format('YYYYMMDDHHmmss')}${this.getRandom4Digits()}`;
          ybRequest.body.mdtrtarea_admvs = userData.mdtrtareaAdmvs;
          ybRequest.body.recer_sys_code = '007';
          ybRequest.body.infver = 'V1.0';
          ybRequest.body.opter_type = '1';
          ybRequest.body.opter = userData.clinicCode;
          ybRequest.body.opter_name = userData.staffName;
          ybRequest.body.inf_time = dayjs().format('YYYY-MM-DD HH:mm:ss');
          ybRequest.body.fixmedins_code = userData.clinicCode;
          ybRequest.body.fixmedins_name = userData.clinicName;
          ybRequest.body.sign_no = this.signNo;
          ybRequest.body.input.signOut = {
            sign_no: this.signNo,
            opter_no: userData.staffId,
          }
          // 设置签退参数
          console.log('设置签退参数: sign_no=', this.signNo, 'opter_no=', userData.staffId);


          // 4. 构建传给后端的newItem
          console.log('步骤3: 构建传给后端的newItem');
          const newItem = {
            infno: 9002,
            mdtrtareaAdmvs: userData.mdtrtareaAdmvs,
            data: JSON.stringify(ybRequest.body),
            patientId: userData.staffId,
            patientName: userData.staffName
          }
          console.log('newItem内容:', JSON.stringify(newItem, null, 2));

          // 5. 调用addYbRquestData接口
          console.log('步骤4: 调用addYbRquestData接口');
          this.addStepMessage('正在准备医保签退数据...');
          const res = await addYbRquestData(newItem);

          if (res.code !== 200) {
            console.error('addYbRquestData调用失败:', res);
            this.addStepMessage(`医保数据准备失败: ${res.message}`, {level: 'error'});
            return false;
          }

          console.log('addYbRquestData调用成功:', res);
          this.addStepMessage('医保数据准备完成，开始调用接口...');
          this.lyToqtId = res.data.id;

          // 6. 解析响应并设置请求头
          console.log('步骤5: 解析响应并设置请求头');
          let responseData = res.data;
          if (typeof responseData === 'string') {
            console.log('响应数据是字符串，尝试解析JSON...');
            try {
              responseData = JSON.parse(responseData);
            } catch (parseError) {
              console.error('解析医保响应数据失败:', parseError);
              this.addStepMessage('解析医保响应数据失败', {level: 'error'});
              return false;
            }
          }

          // 设置请求头
          ybRequest.headers.infosyscode = responseData.infosyscode;
          ybRequest.headers.hsf_signature = responseData.signature;
          ybRequest.headers.fixmedins_code = userData.clinicCode;
          ybRequest.headers.hsf_nonce = responseData.hsfNonce;
          ybRequest.headers.hsf_timestamp = responseData.hsfTimestamp;
          console.log('请求头设置完成:', ybRequest.headers);

          // 7. 调用医保签退接口
          console.log('步骤6: 调用医保签退接口');
          const axiosConfig = {
            method: 'post',
            url: process.env.VUE_APP_BASE_YBHOST+`/eapdomain/callService`,
            baseURL: '',
            headers: ybRequest.headers,
            data: ybRequest.body,
          };
          console.log('axiosConfig:', JSON.stringify(axiosConfig, null, 2));

          const response = await axios(axiosConfig);
          this.qtResult = response;
          console.log('医保签退响应结果:', this.qtResult);
          this.addStepMessage('医保签退接口调用完成');

          // 8. 处理结果
          console.log('步骤7: 处理签退结果');
          if (this.qtResult.infcode === 0) {
            console.log('医保签退成功');

            // 9. 保存响应到后端
            console.log('步骤8: 保存响应到后端');
            const saveSuccess = await this.saveYbResponse(this.qtResult, 'signOut');
            if (!saveSuccess) {
              console.warn('保存医保签退响应失败');
              this.addStepMessage('医保签退记录保存失败', {level: 'warning'});
            }

            this.signNo = '';
            this.addStepMessage('医保已签退，正在进行重新签到...');

            // 10. 执行重新签到
            console.log('步骤9: 执行重新签到');
            const signInSuccess = await this.handleYbSignIn(userData);

            return signInSuccess;
          } else {
            console.error('医保签退失败:', this.qtResult.err_msg);
            this.addStepMessage(`医保签退失败: ${this.qtResult.err_msg}`, {level: 'error'});
            return false;
          }
        } else {
          // 签到编号未过期
          console.log('签到编号未过期，直接重新签到');
          this.addStepMessage('医保已签到，正在登录中...', {level: 'info'});

          // 11. 直接执行重新签到
          this.addStepMessage('正在重新执行医保签到...');
          const signInSuccess = await this.handleYbSignIn(userData);

          return signInSuccess;
        }

      } catch (error) {
        console.error('签退过程中出错:', error);
        this.addStepMessage(`医保签退异常: ${error.message}`, {level: 'error'});
        return false;
      } finally {
        console.log('===== 医保签退流程结束 =====');
      }
    },

    // 新增方法：保存签到/签退结果
    async saveSignResult(data, id, type) {
      try {
        const params = {
          data: JSON.stringify(data),
          id: id,
          type: type,
          timestamp: dayjs().format('YYYY-MM-DD HH:mm:ss')
        };

        const res = await toUploadLY(params);
        if (res.code === 200) {
          this.addStepMessage(`${type === 'signIn' ? '签到' : '签退'}记录已存档`);
        }
      } catch (error) {
        console.error('保存失败:', error);
      }
    },

    // 生成签名方法
    generateSignature(timestamp, secret, nonce) {
      const rawString = `${timestamp}${secret}${nonce}`;
      return sha256(rawString); // 使用导入的sha256
    },

    // 生成随机字符串（用于签名nonce）
    // 保留原有的nonce生成方法
    // generateNonce() {
    //   return crypto.randomBytes(16).toString('hex');
    // },
    generateBrowserNonce(length = 32) {
      const array = new Uint8Array(length);
      window.crypto.getRandomValues(array);
      return Array.from(array, byte =>
          byte.toString(16).padStart(2, '0')
      ).join('');
    },

    getRandom4Digits() {
      return Math.floor(1000 + Math.random() * 9000).toString();
    },
    async setUserWatermark(user) {
      try {
        const clinicList = await doccliniclist();
        const clinic = clinicList.data.find(item => item.id === user.clinicId);
        const clinicName = clinic ? clinic.name : '未知诊所';
        const currentDate = dayjs().format('YYYY-MM-DD');
        const watermarkText = `${clinicName}-${user.staffName}-${currentDate}`;

        // 主存储
        localStorage.setItem('watermarkText', watermarkText);

        // 分散存储校验信息
        sessionStorage.setItem('w_part1', clinicName);
        localStorage.setItem('w_part2', user.staffName);
        sessionStorage.setItem('w_part3', currentDate);
        localStorage.setItem('w_hash', this.generateHash(watermarkText));

        watermark.set(watermarkText);
      } catch (error) {
        watermark.set('九阵软件');
      }
    },
    //  formatProgress(percentage) {
    //   return percentage === 100 ? '登录成功!' : `登录中 ${percentage}%`
    // },

    // 生成简单hash
    generateHash(text) {
      let hash = 0;
      for (let i = 0; i < text.length; i++) {
        hash = ((hash << 5) - hash) + text.charCodeAt(i);
        hash |= 0; // Convert to 32bit integer
      }
      return hash.toString();
    },
    generateFallbackNonce(length = 32) {
      let result = '';
      const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
      for (let i = 0; i < length; i++) {
        result += chars.charAt(Math.floor(Math.random() * chars.length));
      }
      return result;
    },
    // 简单签名生成（替代SHA256）
    // generateSimpleSignature(t, s, n) {
    //   return window.btoa(unescape(encodeURIComponent(`${t}${s}${n}`)));
    // },
  },

};
</script>

<style lang="less" scoped>
.login-app {
  // 添加样式
  .step-messages {
    /* 错误消息样式 */

    .message-error {
      color: #f56c6c; /* 红色 */
      background-color: #fef0f0;
      border-left: 3px solid #f56c6c;
      padding: 5px 10px;
      border-radius: 4px;
      margin: 3px 0;
    }

    /* 成功消息样式 */

    .message-success {
      color: #67c23a; /* 绿色 */
      background-color: #f0f9eb;
      border-left: 3px solid #67c23a;
      padding: 5px 10px;
      border-radius: 4px;
      margin: 3px 0;
    }

    /* 普通消息样式 */

    .message-info {
      color: #909399;
      padding: 5px 10px;
      margin: 3px 0;
    }
  }

  .login-cont {
    /deep/ .el-progress-bar__inner {
      transition: all 0.4s ease;
    }

    /deep/ .el-progress__text {
      font-size: 14px;
      color: #409EFF;
      font-weight: bold;
    }
  }

  width: 100%;
  height: 100%;

  .filter {
    position: fixed;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    filter: blur(4px);
    align-items: center;
    background-color: var(--white);
    background: url("@/assets/images/loginbg.png");
    /* 决定背景图像的位置是在视口内固定，或者随着包含它的区块滚动。 */
    /* https://developer.mozilla.org/zh-CN/docs/Web/CSS/background-attachment */
    background-attachment: fixed;
    background-position: center;
    background-repeat: no-repeat;
    background-size: cover;
    display: grid;
    height: 100vh;
    place-items: center;
  }

  /* 新增背景容器样式 */

  .background-container {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    overflow: hidden;
    transition: filter 0.5s ease;

    .background-image {
      position: absolute;
      width: 100%;
      height: 100%;
      background: url("@/assets/images/loginbg.png") center/cover fixed;
      transition: transform 0.5s ease;
    }

    &.blur-active {
      filter: blur(4px);

      .background-image {
        transform: scale(1.05); // 添加轻微放大效果增强视觉层次
      }
    }
  }

  //不是每个人都能访问后端的接口，
  //解决方法：把一个令牌，token，存储到本地存储
  .spoken {
    width: 400px;
    height: 120px;
    position: fixed;
    top: 36%;
    right: 0;
    left: 18%;
    bottom: 0;
    border-radius: 10px;
    display: flex;
    padding: 20px;

    span {
      font-size: 48px;
      font-weight: bold;
      color: #347ebc;
      font-family: 'Microsoft JhengHei'; /* 使用Open Sans或备用字体 */
    }
  }

  .bg {
    width: 100%;
    height: 237px;
    background: #347ebc;
    opacity: 0.6;
    position: absolute;
    left: 0;
    top: 0px;
    right: 0px;
    bottom: 0px;
    margin: auto;

    .title {
      font-size: 48px;
      color: #fff;
      line-height: 235px;
      position: absolute;
      left: 15%;
    }

    .cont {
      font-size: 20px;
      color: #fff;
      line-height: 235px;
      position: absolute;
      top: 50px;
      left: 18%;
    }
  }

  .login-form {
    position: fixed;
    opacity: 0.8;
    top: 50%;
    right: 0;
    left: 60%;
    bottom: 0;
    transform: translateY(-50%);
    width: 500px;
    height: 500px;
    background-color: #fff;
    box-shadow: 0 0.9rem 1.7rem rgba(0, 0, 0, 0.25),
    0 0.7rem 0.7rem rgba(0, 0, 0, 0.22);
    border-radius: 10px;
    display: flex;
    padding: 20px;

    .login-left {

    }

    .login-right {
      flex: 1;
      padding: 20px;

      .container__form {
        height: 100%;
        position: absolute;
        top: 0;
        transition: all 0.6s ease-in-out;
      }

      /* 新增加载动画 */
      @keyframes fadeIn {
        from {
          opacity: 0;
          transform: translateY(20px);
        }
        to {
          opacity: 1;
          transform: translateY(0);
        }
      }

      .login-cont {
        padding: 20px;
        padding-top: 0;
        animation: fadeIn 0.6s ease;
        background-color: #fff;
        width: 100%;

        .forget {
          font-size: 12px;
          display: block;
          margin-top: -20px;
        }

        .forget:hover {
          color: #347ebc;
          cursor: pointer;
        }
      }

      .choose {
        display: flex;
        align-items: center;
        justify-content: space-between;

        h3 {
          font-size: 24px;
          font-weight: 500;
          margin-bottom: 20px;
          color: #000;
          margin-top: 20px;
          font-weight: bold;
        }

        span {
          font-size: 14px;
        }
      }

      h2 {
        text-align: center;
        font-size: 28px;
      }

      .el-button {
        width: 100%;
        border: none;
        margin-top: 20px;
      }
    }
  }
}

.chose {
  display: flex;
  justify-content: space-between;

  span {
    color: #aaa;
    font-size: 14px;
  }

  .content {
    width: 400px;

    .el-select {
      width: 100%;
    }
  }

  .login-progress-container {
    padding: 20px;

    .status-messages {
      margin-bottom: 20px;

      .status-item {
        display: flex;
        justify-content: space-between;
        align-items: center;
        padding: 8px 0;
        border-bottom: 1px solid #eee;

        .status-icon {
          margin-left: 10px;
        }
      }
    }

    /deep/ .el-progress-bar {
      padding-right: 50px;
      margin-right: -50px;
    }

    /deep/ .el-progress__text {
      font-size: 14px;
      color: #409EFF;
    }
  }
}

</style>
